﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using SampleWeb.Data;
using System.Data.Objects;
using System.Drawing;
using System.Data.SqlClient;

namespace SampleWeb
{
    public partial class CRUDGridViewAutoPagingAndSorting : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(this.GridView1.SortExpression))
            {
                this.GridView1.Sort("DueOn", SortDirection.Ascending);
            }

            this.ErrorMessageLabel.Visible = false;
        }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            this.GenericDataSource1.ExecuteInsert += new EventHandler<GenericDataSourceControl.GenericDataArgs>(GenericDataSource1_ExecuteInsert);
            this.GenericDataSource1.ExecuteUpdate += new EventHandler<GenericDataSourceControl.GenericUpdateArgs>(GenericDataSource1_ExecuteUpdate);
            this.GenericDataSource1.ExecuteDelete += new EventHandler<GenericDataSourceControl.GenericKeyDataArgs>(GenericDataSource1_ExecuteDelete);

            this.DetailsView1.ItemInserted += new DetailsViewInsertedEventHandler(DetailsView1_ItemInserted);

            //Adding "Complete" command functionality:
            this.GridView1.RowCommand += new GridViewCommandEventHandler(GridView1_RowCommand);
            this.GridView1.RowDataBound += new GridViewRowEventHandler(GridView1_RowDataBound);


            //Add some SQL logging & custom paging paging support
            this.GridView1.DataBound += new EventHandler(GridView1_DataBound);
        }

        /// <summary>
        /// Adds some row DELETE confirmation.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void  GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.DataRow && (sender as GridView).EditIndex != e.Row.RowIndex)
            {
                var delete = e.Row.Cells[e.Row.Cells.Count - 1].Controls.OfType<IButtonControl>().SingleOrDefault(p => p.CommandName == "Delete");

                var taskName = (e.Row.DataItem as Task).Title;
                (delete as LinkButton).OnClientClick = string.Format("return confirm('Are you sure you want to delete this task: {0}');", taskName);
            }
        }

        void GridView1_DataBound(object sender, EventArgs e)
        {
            (this.Master as SiteMaster).Log(ModelDataContext.Instance.Log.ToString());

            //data bind the custom pager
            (this.GridView1.BottomPagerRow.FindControl("PagingRepeater") as Repeater).DataSourceID = "PagingData";
            this.GridView1.BottomPagerRow.DataBind();
        }

        protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            switch (e.CommandName)
            {
                case "Complete":
                case "ReOpen":
                    var rowIndex = int.Parse(e.CommandArgument.ToString());

                    //Get the Task key: TaskID
                    var taskID = (Guid)(sender as GridView).DataKeys[rowIndex]["TaskID"];

                    //Get the Task:
                    var theTask = ModelDataContext.Instance.Tasks.Single(p => p.TaskID == taskID);

                    //settting the Task as "Complete" TRUE/FALSE
                    theTask.Completed = e.CommandName == "Complete";
                    ///submit the changes back to the database
                    ModelDataContext.Instance.SubmitChanges();

                    //Refresh the UI
                    (sender as GridView).DataBind();
                    break;
            }
        }

        /// <summary>
        /// Handles the Paging Repeater Item Command. Since the Paging buttons are inside a Repeater they cannot trigger commands for the GridView.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void PagingRepeater_ItemCommand(object sender, RepeaterCommandEventArgs e)
        {
            if (e.CommandName == "Page")
            {
                this.GridView1.PageIndex = Convert.ToInt32(e.CommandArgument);
                this.GridView1.DataBind();
            }
        }

        /// <summary>
        /// Handled the DetailsView.ItemInserted event;
        /// on a successfull operation it DataBinds the GridView, else it displays error message and handles the Insert Exception.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void DetailsView1_ItemInserted(object sender, DetailsViewInsertedEventArgs e)
        {
            if (e.Exception == null)
            {
                //Just call the DataBind method and this will trigger the GenericDataSource to refresh.
                this.GridView1.DataBind();
            }
            else
            {
                this.ErrorMessageLabel.Text = "Error inserting new Task";
                this.ErrorMessageLabel.Visible = true;
                e.ExceptionHandled = true;
                e.KeepInInsertMode = true;
            }
        }

        void GenericDataSource1_ExecuteDelete(object sender, GenericDataSourceControl.GenericKeyDataArgs e)
        {
            //Get the TaskID key; this value must be set on the GridView.DataKeyNames
            var oldTask = e.GetDataItem<Task>();
            //mark the Entity for deletion, then just Submit the changes back to the database
            var theTask = ModelDataContext.Instance.Tasks.Single(p => p == oldTask);
            ModelDataContext.Instance.Tasks.DeleteOnSubmit(theTask);
            ModelDataContext.Instance.SubmitChanges();
        }

        void GenericDataSource1_ExecuteUpdate(object sender, GenericDataSourceControl.GenericUpdateArgs e)
        {
            //Get the TaskID key; this value must be set on the GridView.DataKeyNames
            var task = e.GetDataItem<Task>();
            var oldTask = e.GetOldDataItem<Task>();

            ModelDataContext.Instance.Tasks.Attach(task, oldTask);
            //submit the change back to the database:
            ModelDataContext.Instance.SubmitChanges();

            //Remark:
            //it is also possible just to retrieve the DataItem, fill it with the data binding values and just Submit Changes back to database.
            //var theTask = ModelDataContext.Instance.Tasks.Single(p => p.TaskID == taskID);
            //e.FillDataItem(theTask);
        }

        void GenericDataSource1_ExecuteInsert(object sender, GenericDataSourceControl.GenericDataArgs e)
        {
            //create the new task object to be inserted
            //var newTask = e.DataItem.Value<Task>();
            var newTask = e.GetDataItem<Task>();
            newTask.TaskID = Guid.NewGuid();
            newTask.CreatedOn = DateTime.Now;

            //Add the new Task and submit the changes.
            ModelDataContext.Instance.Tasks.InsertOnSubmit(newTask);
            ModelDataContext.Instance.SubmitChanges();
        }

        protected void GenericDataSource1_ExecuteSelect(object sender, GenericDataSourceControl.GenericSelectArgs e)
        {
            //Just setup the DataSource
            e.SetData(ModelDataContext.Instance.Tasks);
        }

        protected void PagingData_ExecuteSelect(object sender, GenericDataSourceControl.GenericSelectArgs args)
        {
            if (this.GridView1.PageCount != 0)
            {
                var theResult = new List<int>();
                for (int i = 0; i < this.GridView1.PageCount; i++)
                {
                    theResult.Add(i);
                }

                args.SetData(theResult);
            }
        }
    }
}
